//
//  Copyright (C) 1998-2007 J. Andrew McLaughlin
//  Copyright (C) 2009 Vadim Ushakov
// 
//  This program is free software; you can redistribute it and/or modify it
//  under the terms of the GNU General Public License as published by the Free
//  Software Foundation; either version 2 of the License, or (at your option)
//  any later version.
// 
//  This program is distributed in the hope that it will be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
//  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
//  for more details.
//  
//  You should have received a copy of the GNU General Public License along
//  with this program; if not, write to the Free Software Foundation, Inc.,
//  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

// This goes with the file kernelWindow.c

#if !defined(_KERNELWINDOW_H)

#include "zinput/kernelMouse.h"
#include "kernelGraphic.h"
#include "kernelText.h"
#include "kernelVariableList.h"
#include <string.h>
#include <sys/window.h>

// Definitions

#define WINDOW_TITLEBAR_HEIGHT              19
#define WINDOW_TITLEBAR_MINWIDTH            (WINDOW_TITLEBAR_HEIGHT * 4)
#define WINDOW_BORDER_THICKNESS             3
#define WINDOW_SHADING_INCREMENT            15
#define WINDOW_RADIOBUTTON_SIZE             10
#define WINDOW_CHECKBOX_SIZE                10
#define WINDOW_MIN_WIDTH                    (WINDOW_TITLEBAR_MINWIDTH + (WINDOW_BORDER_THICKNESS * 2))
#define WINDOW_MIN_HEIGHT                   (WINDOW_TITLEBAR_HEIGHT + (WINDOW_BORDER_THICKNESS * 2))
#define WINDOW_MINREST_TRACERS              20
#define WINDOW_DEFAULT_CONFIG               "/system/config/window.conf"
#define WINDOW_DEFAULT_DESKTOP_CONFIG       "/system/config/desktop.conf"
#define WINDOW_DEFAULT_VARFONT_SMALL_FILE   "/system/fonts/arial-bold-10.bmp"
#define WINDOW_DEFAULT_VARFONT_SMALL_NAME   "arial-bold-10"
#define WINDOW_DEFAULT_VARFONT_MEDIUM_FILE  "/system/fonts/arial-bold-12.bmp"
#define WINDOW_DEFAULT_VARFONT_MEDIUM_NAME  "arial-bold-12"

#define WINFLAG_SKIP_TASKBAR                0x0400
#define WINFLAG_VISIBLE                     0x0200
#define WINFLAG_ENABLED                     0x0100
#define WINFLAG_MOVABLE                     0x0080
#define WINFLAG_RESIZABLE                   0x0060
#define WINFLAG_RESIZABLEX                  0x0040
#define WINFLAG_RESIZABLEY                  0x0020
#define WINFLAG_HASBORDER                   0x0010
#define WINFLAG_CANFOCUS                    0x0008
#define WINFLAG_HASFOCUS                    0x0004
//#define WINFLAG_BACKGROUNDTILED             0x0002
#define WINFLAG_DEBUGLAYOUT                 0x0001

#define WINNAME_TEMPCONSOLE                 "temp console window"
#define WINNAME_ROOTWINDOW                  "root window"

typedef struct {
	struct {
		int minWidth;
		int minHeight;
		int minRestTracers;
		int displayDragging;
		int padding;
		struct {
			int thickness;
			int shadingIncrement;
		} border;
	} window;

	struct {
		int height;
		int minWidth;
		struct {
			color background_color;
			color foreground_color;
		} active;
		struct {
			color background_color;
			color foreground_color;
		} inactive;
	} titleBar;

	struct {
		int thickness;
		int shadingIncrement;
	} border;

	struct {
		int size;
	} radioButton;

	struct {
		int size;
	} checkbox;

	struct {
		kernelAsciiFont *defaultFont;
		struct {
			struct {
				char file[MAX_PATH_NAME_LENGTH];
				char name[MAX_NAME_LENGTH];
				kernelAsciiFont *font;
			} small;
			struct {
				char file[MAX_PATH_NAME_LENGTH];
				char name[MAX_NAME_LENGTH];
				kernelAsciiFont *font;
			} medium;
		} varWidth;
		int use_default_if_error;
	} font;

	struct {
		int draw_layout_grid;
	} debug;

} kernelWindowVariables;

typedef enum {
	genericComponentType,
	borderComponentType,
	buttonComponentType,
	canvasComponentType,
	checkboxComponentType,
	containerComponentType,
	iconComponentType,
	imageComponentType,
	listComponentType,
	listItemComponentType,
	menuComponentType,
	menuBarComponentType,
	progressBarComponentType,
	radioButtonComponentType,
	scrollBarComponentType,
	sliderComponentType,
	sysContainerComponentType,
	textAreaComponentType,
	textLabelComponentType,
	titleBarComponentType,
	windowType

} kernelWindowObjectType;

// Forward declarations, where necessary
struct _kernelWindow;
struct _kernelWindowComponent;
typedef volatile struct _kernelWindow kernelWindow;
typedef volatile struct _kernelWindowComponent kernelWindowComponent;



// The object that defines a GUI window
struct _kernelWindow {
	kernelWindowObjectType type;
	int processId;
	char* title;
	int titleSize;
	int xCoord;
	int yCoord;
	int level;
	int layer;
	unsigned flags;
	kernelGraphicBuffer * buffer;
	image backgroundImage;
	backgroundImageMode backgroundImageMode;
	color background;
	windowEventStream events;
	variableList* tags;
	kernelWindowComponent *titleBar;
	kernelWindowComponent *borders[4];
	kernelWindowComponent *menuBar;
	kernelWindowComponent *contextMenu;
	kernelWindowComponent *sysContainer;
	kernelWindowComponent *mainContainer;
	kernelWindowComponent *focusComponent;
	kernelWindowComponent *oldFocusComponent;
	int pointer;

	volatile struct _kernelWindow *parentWindow;
	volatile struct _kernelWindow *dialogWindow;

	// Routines for managing this window
	//int (*_draw) (volatile struct _kernelWindow *);
	int (*_drawClip) (volatile struct _kernelWindow *, int, int, int, int);
	int (*_update) (volatile struct _kernelWindow *, int, int, int, int);
	int (*_focusNextComponent) (volatile struct _kernelWindow *);
	int (*_changeComponentFocus) (volatile struct _kernelWindow *, kernelWindowComponent *);

};


#define makeWindowScreenArea(windowP)                                 \
   &((screenArea) { windowP->xCoord, windowP->yCoord,                 \
                   (windowP->xCoord + (windowP->buffer->width - 1)),   \
                   (windowP->yCoord + (windowP->buffer->height - 1)) } )


kernelWindow *getWindow(objectKey);

static inline int isPointInside(int xCoord, int yCoord,	screenArea *area)
{
	// Return 1 if point 1 is inside area 2
  
	if ((xCoord < area->leftX) || (xCoord > area->rightX) ||
	    (yCoord < area->topY ) || (yCoord > area->bottomY))
		return (0);
	else
		// Yup, it's inside
		return (1);
}

static inline int doLinesIntersect(int horizX1, int horizY, int horizX2, int vertX, int vertY1, int vertY2)
{
	// True if the horizontal line intersects the vertical line

	if ((vertX < horizX1) || (vertX > horizX2) || ((horizY < vertY1) || (horizY > vertY2)))
		return (0);
	else
		// Yup, they intersect
		return (1);
}

static inline int doAreasIntersect(screenArea *firstArea, screenArea *secondArea)
{
	// Return 1 if area 1 and area 2 intersect.

	if (isPointInside(firstArea->leftX, firstArea->topY, secondArea) ||
	    isPointInside(firstArea->rightX, firstArea->topY, secondArea) ||
	    isPointInside(firstArea->leftX, firstArea->bottomY, secondArea) ||
	    isPointInside(firstArea->rightX, firstArea->bottomY, secondArea) ||
	    isPointInside(secondArea->leftX, secondArea->topY, firstArea) ||
	    isPointInside(secondArea->rightX, secondArea->topY, firstArea) ||
	    isPointInside(secondArea->leftX, secondArea->bottomY, firstArea) ||
	    isPointInside(secondArea->rightX, secondArea->bottomY, firstArea))
		return (1);
	else if (doLinesIntersect(firstArea->leftX, firstArea->topY,
			firstArea->rightX,
			secondArea->leftX, secondArea->topY,
			secondArea->bottomY) ||
	         doLinesIntersect(secondArea->leftX, secondArea->topY,
			    secondArea->rightX,
			    firstArea->leftX, firstArea->topY,
			    firstArea->bottomY))
		return (1);
	else
		// Nope, not intersecting
		return (0);
}


// Functions exported by kernelWindow*.c functions
int kernelWindowInitialize(void);
int kernelWindowStart(void);
kernelWindow *kernelWindowMakeRoot(void);
int kernelWindowShell(int, int);
void kernelWindowShellUpdateList(void);
int kernelWindowLogin(const char *);
int kernelWindowLogout(void);
void kernelWindowRefresh(void);
kernelWindow *kernelWindowNew(int, const char *);
kernelWindow *kernelWindowNewDialog(kernelWindow *, const char *);
int kernelWindowDestroy(kernelWindow *);
objectKey kernelWindowGetParent(objectKey window);

int kernelWindowSetTitle(kernelWindow *, const char *);
int kernelWindowGetTitle(kernelWindow *, char *, int);
int kernelWindowGetSize(kernelWindow *, int *, int *);
int kernelWindowSetSize(kernelWindow *, int, int);
int kernelWindowGetLocation(kernelWindow *, int *, int *);
int kernelWindowSetLocation(kernelWindow *, int, int);
int kernelWindowSetLayer(objectKey, int);
int kernelWindowGetLayer(objectKey);
int kernelWindowGetLayerVirtual(objectKey);
int kernelWindowCenter(kernelWindow *);
int kernelWindowSnapIcons(objectKey);

int kernelWindowSetHasBorder(kernelWindow *, int);
int kernelWindowSetHasTitleBar(kernelWindow *, int);

int kernelWindowSetFlag(kernelWindow *, unsigned, int);
int kernelWindowGetFlag(kernelWindow *, unsigned);

int kernelWindowSetMovable(kernelWindow *, int);
int kernelWindowSetResizable(kernelWindow *, int);
int kernelWindowSetSkipTaskbar(kernelWindow *, int);

int kernelWindowGetMovable(kernelWindow *);
int kernelWindowGetResizable(kernelWindow *);
int kernelWindowGetSkipTaskbar(kernelWindow *);

int kernelWindowRemoveMinimizeButton(kernelWindow *);
int kernelWindowRemoveCloseButton(kernelWindow *);

int kernelWindowSetColors(kernelWindow *, color *);
int kernelWindowSetVisible(kernelWindow *, int);
void kernelWindowSetMinimized(kernelWindow *, int);
int kernelWindowAddConsoleTextArea(kernelWindow *);
void kernelWindowResetColors(void);
void kernelWindowProcessEvent(windowEvent *);
int kernelWindowRegisterEventHandler(kernelWindowComponent *,
				     void (*)(kernelWindowComponent *,
					      windowEvent *));
int kernelWindowComponentEventGet(objectKey, windowEvent *);
int kernelWindowComponentSetNotifiedProcess(objectKey key, int processId);
variableList* kernelWindowComponentGetTagList(objectKey);
int kernelWindowScreenShot(image *);
int kernelWindowSaveScreenShot(const char *);
int kernelWindowSetTextOutput(kernelWindowComponent *);
int kernelWindowLayout(kernelWindow *);
void kernelWindowDebugLayout(kernelWindow *);
int kernelWindowContextAdd(objectKey, windowMenuContents *);
int kernelWindowContextSet(objectKey, kernelWindowComponent *);
int kernelWindowSwitchPointer(objectKey, const char *);
int kernelWindowEnumerateWindows(objectKey* buffer, int bufferSize);
void kernelWindowMoveConsoleTextArea(kernelWindow *, kernelWindow *);


int kernelWindowUpdate(objectKey, int, int, int, int);
int kernelWindowUpdateBuffer(kernelGraphicBuffer *, int, int, int, int);

int kernelWindowDrawClip(objectKey, int, int, int, int);
int kernelWindowDraw(objectKey);

void kernelWindowRedrawArea(int, int, int, int);
void kernelWindowDrawAll(void);

int kernelWindowFocusNextComponent(objectKey);
int kernelWindowChangeComponentFocus(objectKey, objectKey);

int kernelWindowSetBackgroundImageMode(kernelWindow *, backgroundImageMode);
int kernelWindowGetBackgroundImageMode(kernelWindow *);
int kernelWindowSetBackgroundImage(kernelWindow *, image *);
int kernelWindowLoadBackgroundImageFromFile(kernelWindow *, const char *, backgroundImageMode);
int kernelWindowRootLoadBackgroundImageFromFile(const char *, backgroundImageMode);

#define _KERNELWINDOW_H
#endif
